This document provides the complete API reference for sending events to Flexprice. It includes all endpoints, request/response formats, error codes, and examples.

Base URL

https://api.cloud.flexprice.io/v1

Authentication

All requests require authentication using an API key in the request header:
x-api-key: <your_api_key>
Security Note: Keep your API key secure and never expose it in client-side code or public repositories.

Endpoints

Single Event

Send a single event to Flexprice. Endpoint: POST /events Headers:
Content-Type: application/json
x-api-key: <your_api_key>
Request Body:
{
  "event_name": "string",
  "external_customer_id": "string",
  "properties": {
    "string": "any"
  },
  "event_id": "string",
  "timestamp": "string",
  "source": "string"
}
Response:
  • Status: 202 Accepted
  • Body:
{
  "event_id": "string",
  "message": "Event accepted for processing"
}

Bulk Events

Send multiple events in a single request for better performance. Endpoint: POST /events/bulk Headers:
Content-Type: application/json
x-api-key: <your_api_key>
Request Body:
{
  "events": [
    {
      "event_name": "string",
      "external_customer_id": "string",
      "properties": {
        "string": "any"
      },
      "event_id": "string",
      "timestamp": "string",
      "source": "string"
    }
  ]
}
Response:
  • Status: 202 Accepted
  • Body:
{
  "event_ids": ["string"],
  "message": "Events accepted for processing"
}

Request Fields

Required Fields

FieldTypeDescriptionExample
event_namestringMust exactly match your feature’s Event Name"model.usage"
external_customer_idstringYour identifier for the customer"cust_123"

Conditional Fields

FieldTypeWhen RequiredDescriptionExample
propertiesobjectFor Sum, Max, Latest, Unique CountContains values to aggregate{"credits": 2}
properties.<field>number/stringWhen aggregation field is setExact field name from feature config2 or "user_123"

Optional Fields

FieldTypeDescriptionExample
event_idstringYour unique identifier for the event"evt_abc123"
timestampstringISO 8601 UTC timestamp"2025-08-22T07:05:49.441Z"
sourcestringOrigin of the event"api", "worker"

Data Types

Property Values

  • Numbers: Use for Sum, Max aggregations
    "properties": { "credits": 2 }
    
  • Strings: Use for Unique Count, Latest aggregations
    "properties": { "user_id": "user_123" }
    

Timestamps

  • Format: ISO 8601 UTC
  • Example: "2025-08-22T07:05:49.441Z"
  • Default: Server time if omitted

Examples

Basic Event (Count Aggregation)

curl --request POST \
  --url https://api.cloud.flexprice.io/v1/events \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <your_api_key>' \
  --data '{
    "event_name": "api.calls",
    "external_customer_id": "cust_123"
  }'

Event with Properties (Sum Aggregation)

curl --request POST \
  --url https://api.cloud.flexprice.io/v1/events \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <your_api_key>' \
  --data '{
    "event_name": "model.usage",
    "external_customer_id": "cust_123",
    "properties": {
      "credits": 2
    }
  }'

Complete Event

curl --request POST \
  --url https://api.cloud.flexprice.io/v1/events \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <your_api_key>' \
  --data '{
    "event_name": "model.usage",
    "external_customer_id": "cust_123",
    "properties": {
      "credits": 2,
      "model": "gpt-4",
      "region": "us-east-1"
    },
    "event_id": "evt_abc123",
    "timestamp": "2025-08-22T07:05:49.441Z",
    "source": "api"
  }'

Bulk Events

curl --request POST \
  --url https://api.cloud.flexprice.io/v1/events/bulk \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <your_api_key>' \
  --data '{
    "events": [
      {
        "event_name": "model.usage",
        "external_customer_id": "cust_123",
        "properties": { "credits": 2 }
      },
      {
        "event_name": "model.usage",
        "external_customer_id": "cust_456",
        "properties": { "credits": 5 }
      }
    ]
  }'

Language Examples

JavaScript (Node.js)

const fetch = require("node-fetch");

async function sendEvent() {
  const response = await fetch("https://api.cloud.flexprice.io/v1/events", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": process.env.FLEXPRICE_API_KEY,
    },
    body: JSON.stringify({
      event_name: "model.usage",
      external_customer_id: "cust_123",
      properties: { credits: 2 },
      source: "api",
    }),
  });

  if (response.status === 202) {
    const result = await response.json();
    console.log("Event sent:", result);
  } else {
    const error = await response.text();
    console.error("Error:", error);
  }
}

Python

import os
import requests
import json

def send_event():
    url = "https://api.cloud.flexprice.io/v1/events"
    headers = {
        "Content-Type": "application/json",
        "x-api-key": os.environ["FLEXPRICE_API_KEY"]
    }

    data = {
        "event_name": "model.usage",
        "external_customer_id": "cust_123",
        "properties": {"credits": 2},
        "source": "api"
    }

    response = requests.post(url, headers=headers, json=data)

    if response.status_code == 202:
        result = response.json()
        print("Event sent:", result)
    else:
        print("Error:", response.text)

Go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

type Event struct {
    EventName           string                 `json:"event_name"`
    ExternalCustomerID  string                 `json:"external_customer_id"`
    Properties          map[string]interface{} `json:"properties,omitempty"`
    Source              string                 `json:"source,omitempty"`
}

func sendEvent() error {
    event := Event{
        EventName:          "model.usage",
        ExternalCustomerID: "cust_123",
        Properties: map[string]interface{}{
            "credits": 2,
        },
        Source: "api",
    }

    jsonData, err := json.Marshal(event)
    if err != nil {
        return err
    }

    req, err := http.NewRequest("POST", "https://api.cloud.flexprice.io/v1/events", bytes.NewBuffer(jsonData))
    if err != nil {
        return err
    }

    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("x-api-key", os.Getenv("FLEXPRICE_API_KEY"))

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode == 202 {
        fmt.Println("Event sent successfully")
    } else {
        fmt.Printf("Error: HTTP %d\n", resp.StatusCode)
    }

    return nil
}

PHP

<?php

function sendEvent() {
    $url = 'https://api.cloud.flexprice.io/v1/events';
    $apiKey = $_ENV['FLEXPRICE_API_KEY'];

    $data = [
        'event_name' => 'model.usage',
        'external_customer_id' => 'cust_123',
        'properties' => [
            'credits' => 2
        ],
        'source' => 'api'
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'x-api-key: ' . $apiKey
    ]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode == 202) {
        echo "Event sent successfully\n";
    } else {
        echo "Error: HTTP $httpCode\n";
        echo "Response: $response\n";
    }
}

Error Responses

HTTP Status Codes

StatusDescription
202 AcceptedEvent accepted for processing
400 Bad RequestInvalid payload or missing required fields
401 UnauthorizedInvalid or missing API key
429 Too Many RequestsRate limit exceeded

Error Response Format

{
  "error": "Error description",
  "details": "Additional error details"
}

Common Error Messages

Missing Required Field

{
  "error": "Missing required field: event_name"
}

Invalid Event Name

{
  "error": "Event name 'unknown.event' not found"
}

Invalid Customer

{
  "error": "Customer with external_customer_id 'invalid_id' not found"
}

Invalid JSON

{
  "error": "Invalid JSON format"
}

Rate Limit Exceeded

{
  "error": "Rate limit exceeded. Try again later."
}

Rate Limits

  • Single events: 1000 requests per minute
  • Bulk events: 100 requests per minute (up to 1000 events per request)
  • Response: 429 status code when exceeded

Rate Limit Headers

When approaching rate limits, responses include headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 50
X-RateLimit-Reset: 1640995200

Best Practices

1. Error Handling

Implement proper error handling with retries:
async function sendEventWithRetry(eventData, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch("https://api.cloud.flexprice.io/v1/events", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-api-key": process.env.FLEXPRICE_API_KEY,
        },
        body: JSON.stringify(eventData),
      });

      if (response.status === 202) {
        return await response.json();
      }

      if (response.status === 429) {
        // Rate limited - wait and retry
        const retryAfter =
          response.headers.get("Retry-After") || attempt * 1000;
        await new Promise((resolve) => setTimeout(resolve, retryAfter));
        continue;
      }

      throw new Error(`HTTP ${response.status}: ${await response.text()}`);
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      // Wait before retry
      await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
    }
  }
}

2. Bulk Events for High Volume

Use bulk events when sending many events:
const events = [
  { event_name: "api.calls", external_customer_id: "cust_1" },
  { event_name: "api.calls", external_customer_id: "cust_2" },
  // ... more events
];

const response = await fetch("https://api.cloud.flexprice.io/v1/events/bulk", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": process.env.FLEXPRICE_API_KEY,
  },
  body: JSON.stringify({ events }),
});

3. Idempotency

Use event_id for idempotency:
{
  "event_name": "model.usage",
  "external_customer_id": "cust_123",
  "properties": { "credits": 2 },
  "event_id": "unique_event_id_123"
}

4. Timestamps

Include timestamps for historical events:
{
  "event_name": "model.usage",
  "external_customer_id": "cust_123",
  "properties": { "credits": 2 },
  "timestamp": "2025-08-22T07:05:49.441Z"
}

Validation

Event Name Validation

  • Must match a feature’s Event Name exactly
  • Case-sensitive
  • Cannot be changed after feature creation

Customer Validation

  • external_customer_id must exist in Flexprice
  • Customer must be active

Property Validation

  • Aggregation field must exist for Sum, Max, Latest, Unique Count
  • Data types must match aggregation function requirements

Testing

Test Endpoint

For testing purposes, you can use the same endpoints with test data:
curl --request POST \
  --url https://api.cloud.flexprice.io/v1/events \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <your_api_key>' \
  --data '{
    "event_name": "test.feature",
    "external_customer_id": "test_customer",
    "properties": {
      "value": 1
    }
  }'

Validation Checklist

Before sending production events:
  • Feature exists and is active
  • Event Name matches exactly
  • Customer exists in Flexprice
  • Required properties are included
  • Data types are correct
  • API key has proper permissions

Support

For API-related issues:
  1. Check error messages for specific details
  2. Verify your request format matches the examples
  3. Test with a simple event first
  4. Contact support with specific error details and examples